home *** CD-ROM | disk | FTP | other *** search
/ CGI How-To / CGI HOW-TO.iso / chap6 / 6_7 / fork_c / fork.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-15  |  4.4 KB  |  225 lines

  1.  
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "cgilib.h"
  6.  
  7. extern char **environ;
  8.  
  9. char **copyEnvironment(char **environment)
  10. {
  11.     int numEnvvar = 0;
  12.     const char *tmp;
  13.     char **newEnv;
  14.     
  15.     /* Loop through the array */
  16.     
  17.     for( tmp = *environment; '\0' != *tmp; tmp += strlen(tmp)+1 )
  18.     {
  19.         /* Count the number of env var */
  20.         numEnvvar++;
  21.     }
  22.     
  23.     numEnvvar++; /* for the null */
  24.     
  25.     newEnv = malloc(numEnvvar * sizeof(char *));
  26.     
  27.     /* Depending on your machine, you might use memcopy here */
  28.     bcopy(environment,newEnv,(sizeof(char *) * numEnvvar));
  29.     
  30.     return newEnv;
  31. }
  32.  
  33. void setEnvVar(char ***environment, const char *envName, const char * newValue)
  34. {
  35.     if(newValue && envName)
  36.     {
  37.         char *tmp;
  38.         size_t length;
  39.         int gotIt = 0, numEnvvar = 0;
  40.         
  41.         length = strlen(envName);
  42.         
  43.         /* Loop through the array */
  44.         
  45.         for( tmp = **environment; '\0' != *tmp; tmp += strlen(tmp)+1 )
  46.         {
  47.             /* Count the number of env var */
  48.             numEnvvar++;
  49.             
  50.             /* Check if this is the right env variable */
  51.             if ( !(strncmp( tmp, envName, length))
  52.                 &&( '=' == tmp[ length ] ))
  53.             {
  54.                 int newSize;
  55.                 
  56.                 /* Calc the new size, include space for the '=' */
  57.                 newSize = strlen(envName) + strlen(newValue) + 2;
  58.                 
  59.                 /*free(tmp);*/
  60.                 
  61.                 tmp = malloc(sizeof(char) * newSize);
  62.                 
  63.                 strcpy(tmp,envName);
  64.                 strcat(tmp,"=");
  65.                 strcat(tmp,newValue);
  66.                 (*environment)[numEnvvar-1] = tmp;
  67.                 gotIt = 1;
  68.                 break;
  69.             }
  70.         }
  71.         
  72.         numEnvvar++; /* for the null */
  73.         
  74.         if(!gotIt)
  75.         {
  76.             int newSize;
  77.             
  78.             /* Calc the new size, include space for the '=' */
  79.             newSize = strlen(envName) + strlen(newValue) + 2;
  80.             
  81.             tmp = malloc(sizeof(char) * newSize);
  82.             
  83.             strcpy(tmp,envName);
  84.             strcat(tmp,"=");
  85.             strcat(tmp,newValue);
  86.                 
  87.              /* Grow the array by 1*/
  88.             *environment = realloc(*environment,sizeof(char *)*(numEnvvar+1));
  89.             (*environment)[numEnvvar-1] = tmp;
  90.             (*environment)[numEnvvar] = (char *) 0;
  91.         }
  92.     }
  93. }
  94.  
  95. void main(int argc, char *argv[])
  96. {
  97.     /* Variables for the data. */
  98.     
  99.     Dictionary dataDict;
  100.     char *data = (char *)0;
  101.     const char *theScript = (char *)0,*choice = (char *)0;
  102.     int pipeTo[2];
  103.     int pidChild = -1;
  104.     char buffer[16];
  105.     char **newEnviron;
  106.     int numFds,fd;
  107.     
  108.     dataDict = dict_alloc();
  109.     
  110.     /*
  111.      * Get the CGI data from the CGI library
  112.      */
  113.     
  114.     readData(&data);
  115.     if(data) parseData(data,dataDict);
  116.     
  117.     /* figure out which radio button was pressed. */
  118.     
  119.     choice = dict_valueForKey(dataDict,"choice");
  120.     
  121.     if(choice)
  122.     {
  123.         if(!strcmp(choice,"vars"))
  124.         {
  125.             theScript = "envvar";
  126.         }
  127.         else if(!strcmp(choice,"formdata"))
  128.         {
  129.             theScript = "formdata";
  130.         }
  131.         else
  132.         {
  133.             theScript = "fortune.sh";
  134.         }
  135.     }
  136.     else
  137.     {
  138.         theScript = "fortune.sh";
  139.     }
  140.     
  141.     /* Set up the environment */
  142.     
  143.     /* Copy the gloval environment */
  144.     newEnviron = copyEnvironment(environ);
  145.     
  146.     /* Reset the relevent env. var. for the child */
  147.     sprintf(buffer,"POST");
  148.     setEnvVar(&newEnviron,"REQUEST_METHOD",buffer);
  149.     
  150.     sprintf(buffer,"%d",(data)? strlen(data)*sizeof(char) : 0);
  151.     setEnvVar(&newEnviron,"CONTENT_LENGTH",buffer);
  152.     
  153.     /********** Fork the child process ************/
  154.     
  155.     if(theScript)
  156.     {
  157.         /* Create a set of pipes, on will be used to read,the other to write */
  158.         
  159.         if(pipe(pipeTo) < 0)
  160.         {
  161.             fprintf(stderr,"Error creating pipes to subprocess.");
  162.             exit(1);
  163.         }
  164.         
  165.         fflush(stdout);/*flush all output streams */
  166.         
  167.         /* Call fork, use vfork if it is available */
  168.         switch (pidChild = vfork())
  169.         {
  170.             case -1:    /* error */
  171.                 
  172.                 fprintf(stderr,"Error starting UNIX vfork of subprocess.");
  173.                 break;
  174.                 
  175.             case 0:    /* child */
  176.                 
  177.                 /* Use the first pipe as stdin */
  178.                 dup2(pipeTo[0], 0);
  179.                 
  180.                 close(pipeTo[0]);
  181.                 
  182.                 /* Call exec */
  183.                 execle(theScript,theScript, NULL,newEnviron);
  184.         
  185.                 /* We should never get here, because of the exec. */
  186.                 perror("vfork:forkingCGI (child)"); 
  187.                 
  188.                 exit(1);
  189.                 
  190.             default:    /* parent */
  191.                 
  192.                 /* Close the reading pipe, we dont need it */
  193.                 close(pipeTo[0]);
  194.                 
  195.                 /* Write the data to the child */
  196.                 if(data)
  197.                 {
  198.                   int len,remaining,wrote = 0;
  199.  
  200.                   len = strlen(data) * sizeof(char);
  201.                   remaining = len;
  202.                   
  203.                   while(remaining && (wrote >= 0))
  204.                     {
  205.                       wrote = write(pipeTo[1], (char *)data + (len-remaining), remaining);
  206.                       remaining -= wrote;
  207.                     }
  208.  
  209.                 }
  210.                 
  211.                 /* Wait for the child to execute */
  212.                 if((pidChild)&&(wait((union wait *)0) !=pidChild))
  213.                 {
  214.                     /* Close the remaining pipe */
  215.                     close(pipeTo[1]);
  216.                 }
  217.         }
  218.     }
  219.     
  220.     dict_free(dataDict);
  221.     
  222.     /* End the program */
  223.     exit(0);
  224. }
  225.